fix: show protocol handshake failures on the page (#213) - #260
Merged
Conversation
The handshake throws during the first hook mount, so a mismatch left a blank page whose only explanation was a DevTools console message. Every fatal handshake path now routes through `throwVisibly()`, which paints a fixed `#shinyreact-fatal-error` banner (role="alert") carrying the same text before throwing: the major mismatch in either direction, and the npm build's missing-tag / missing-protocolVersion errors. Plain DOM, no dependency on Shiny being initialized — the reported failure is that client and server cannot talk to each other. Literals (both versions, `#shinyreact-config`, `@posit/shinyreact`) are marked with backticks and render as `<code>` chips; the backticks are stripped from the thrown error and the console-only warning. Text is set with textContent, so a server-supplied version cannot inject markup. Colors are #7f1d1d on #fee2e2 (~9.5:1). Tests: unit coverage in config.test.ts for both mismatch directions, chip markup, HTML-injection safety, banner reuse, and throw/display parity; a Playwright e2e (apps/protocol_mismatch) asserting the banner is on screen and the app body never rendered.
# Conflicts: # pkg-js/dist/shinyreact.js # pkg-py/src/shinyreact/www/shinyreact.js # pkg-r/inst/lib/shiny/shinyreact.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #213.
The protocol handshake throws during the first hook mount, so a mismatch left the page blank with the explanation only in the DevTools console.
What changed
Every fatal handshake path now goes through
throwVisibly()inpkg-js/src/shiny-react/config.ts, which paints a fixed banner and then throws the same message:assertProtocolCompatible)#shinyreact-configtagprotocolVersionFail fast is unchanged — the banner is additive.
Details:
<div id="shinyreact-fatal-error" role="alert">appended to<body>, one element reused across repeated failures.#shinyreact-config,@posit/shinyreact) are backticked in the message and render as<code>chips. Backticks are stripped from the thrown error and from the console-only warning.textContent, neverinnerHTML, so a server-supplied version string cannot inject markup.role="alert"carry the meaning.What it looks like
(versions rendered as
<code>chips, dark maroon on a pale red banner across the top)Tests
pkg-js/src/shiny-react/__tests__/config.test.ts: both mismatch directions, chip markup, HTML-injection safety, single-element reuse, throw/display parity, backtick stripping.npx vitest run→ 263 pass.pkg-py/tests/playwright/test_protocol_mismatch.py+ fixtureapps/protocol_mismatch/(server monkeypatched to claim protocol999.0): banner visible with both versions, chips,role="alert", and the app body never rendered.make py-test-e2e→ 11 pass.make py-check-tests→ 146 pass.make js-lintclean.make update-distrun.FEATURES.mdupdated with the new[js]subtree.Not done
No
Shiny.notifications.show()/ dev-mode error console surface. Shiny's error console is fed by server errors, not client throws, and notifications need Shiny initialized — exactly what is unreliable at the moment the handshake fails. Worth revisiting once the npm tier lands.